package com.sinodata.bsm.center.engine.event;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import com.sinodata.bsm.center.util.system.SystemContext;
import com.sinodata.bsm.common.constants.EventConstants;
import com.sinodata.bsm.common.vo.Event;

/**
 * 
 * <p>
 * Description: 事件处理工作流
 * </p>
 *
 * @author liulibo
 * @version 1.0

 * <p>
 * History: 
 *
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-5-29 AM 10:33:15    liulibo        1.0         To create
 * </p>
 *
 * @since 
 * @see
 */
public class EventWorkFlow extends Thread {

    private static final Logger logger = Logger.getLogger("event");

    public static int STATUS_NEW = -1;

    private static EventWorkFlow instance = new EventWorkFlow();

    private final List<EventWorker> workers = new ArrayList<EventWorker>();

    private final List<Event> queue = new ArrayList<Event>();

    private static Object _lock = new Object();

    /** Creates a new instance of EventWorkFlow */
    private EventWorkFlow() {
        initEventChain();
        this.start();
    }

    /**
     * 获取单例
     */
    public static EventWorkFlow getInstance() {
        return instance;
    }

    /**
     * 新建一个事件处理链，进行事件处理，由事件处理链控制其中的每一个环节进行事件处理
     * 
     * @param event
     */
    public synchronized void dispatch(Event event) {
        if (event.getStatus() == null) {
            event.setStatus(EventConstants.STATUS_NEW);
        }
        this.put(event);
    }

    @Override
    public void run() {
        while (true) {
            Event event = this.get();
            try {
                new EventWorkChain(workers, event).run();
            } catch (Exception e) {
                logger.error("event work chain error", e);
            }
        }
    }

    private void initEventChain() {
        FileReader fileReader = null;
        BufferedReader reader = null;
        String appContextPath = (String) SystemContext.getProperty("AppContextPath");
        try {
            fileReader = new FileReader(appContextPath + "WEB-INF/conf/eventflow.conf");
            reader = new BufferedReader(fileReader);
            String readLine;
            EventWorker obj;
            while ((readLine = reader.readLine()) != null) {
                if (readLine.trim().equals("") || readLine.trim().startsWith("#")) {
                    continue;
                }
                obj = (EventWorker) Class.forName(readLine.trim()).newInstance();
                workers.add(obj);
            }
        } catch (Exception e) {
            logger.error("failed to init event chain:", e);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (Exception e) {
                    logger.error("failed to close Inputsream :", e);
                }
            }
            if (fileReader != null) {
                try {
                    fileReader.close();
                } catch (Exception e) {
                    logger.error("failed to close Inputsream :", e);
                }
            }
        }
    }

    private void put(Event event) {
        synchronized (_lock) {
            queue.add(event);
            _lock.notifyAll();
        }
    }

    private Event get() {
        synchronized (_lock) {
            while (queue.size() == 0) {
                try {
                    _lock.wait();
                } catch (InterruptedException e) {
                }
            }
            return queue.remove(0);
        }
    }

}